﻿
//

//


namespace Admin.NET.Core.JsonMapping;

using System.Text.Json.Nodes;
using System.Text.RegularExpressions;

public static class JsonMapper
{
    public static JsonObject Map(JsonObject source, IEnumerable<MappingRule> rules)
    {
        var target = new JsonObject();

        foreach (var rule in rules)
        {
            if (rule.TargetPath.Contains("[*]."))
            {
                HandleArrayMapping(target, source, rule);
            }
            else if (rule.SourcePath.Contains("[*]") && rule.TargetType == TargetType.Array)
            {
                HandleArrayExtraction(target, source, rule);
            }
            else
            {
                HandleSingleValueMapping(target, source, rule);
            }
        }

        return target;
    }

    private static void HandleArrayMapping(JsonObject target, JsonObject source, MappingRule rule)
    {
        Console.WriteLine($"\n========== 🔧 开始处理数组映射 ==========");
        Console.WriteLine($"📌 规则：目标路径 = '{rule.TargetPath}' ← 源路径 = '{rule.SourcePath}'");

        var targetMatch = Regex.Match(rule.TargetPath, @"^(.+)\[\*\]\.(.+)$");
        if (!targetMatch.Success)
        {
            Console.WriteLine("❌ 目标路径格式错误，必须是 '数组名[*].字段名' 格式");
            return;
        }

        var arrayName = targetMatch.Groups[1].Value;
        var propName = targetMatch.Groups[2].Value;
        Console.WriteLine($"📝 解析目标：数组 = '{arrayName}', 字段 = '{propName}'");

        var sourceMatch = Regex.Match(rule.SourcePath, @"^(.+)\[\*\](?:\.(.+))?$");
        if (!sourceMatch.Success)
        {
            Console.WriteLine("❌ 源路径格式错误");
            return;
        }

        var sourceArrayPath = sourceMatch.Groups[1].Value;
        var sourceProp = sourceMatch.Groups[2].Success ? sourceMatch.Groups[2].Value : null;

        Console.WriteLine($"🔍 源数组路径 = '{sourceArrayPath}', 源字段 = '{sourceProp ?? "(整个对象)"}'");

        var sourceArrayNode = source.GetValueOrNull(sourceArrayPath);
        if (sourceArrayNode is not JsonArray sourceArray)
        {
            Console.WriteLine($"❌ 找不到源数组 '{sourceArrayPath}'");
            return;
        }

        Console.WriteLine($"✅ 找到源数组 '{sourceArrayPath}'，共 {sourceArray.Count} 个元素");

        // ✅ 获取现有目标数组（如果已存在），否则创建新数组
        JsonArray targetArray;
        if (target.TryGetPropertyValue(arrayName, out JsonNode? existing) && existing is JsonArray arr)
        {
            Console.WriteLine($"🔁 复用已存在的数组 '{arrayName}'，当前元素数：{arr.Count}");
            targetArray = arr;
        }
        else
        {
            Console.WriteLine($"🆕 创建新数组 '{arrayName}'");
            targetArray = new JsonArray();
            // 初始化数组长度，每个元素是一个空对象
            for (int i = 0; i < sourceArray.Count; i++)
            {
                targetArray.Add(new JsonObject());
            }
        }

        // ✅ 确保目标数组长度足够
        while (targetArray.Count < sourceArray.Count)
        {
            targetArray.Add(new JsonObject());
        }

        for (int i = 0; i < sourceArray.Count; i++)
        {
            var item = sourceArray[i];
            Console.WriteLine($"\n📦 处理第 {i + 1} 个元素：{item?.ToJsonString()}");

            if (item == null) continue;

            JsonNode? sourceValue = null;
            if (sourceProp != null)
            {
                sourceValue = item.GetValueOrNull(sourceProp);
                Console.WriteLine($"  📌 获取 '{sourceProp}' → 值 = {sourceValue?.ToJsonString()}, 类型 = {sourceValue?.GetType().Name}");
            }
            else
            {
                sourceValue = item;
            }

            if (sourceValue == null)
            {
                Console.WriteLine($"  ⚠️ 字段 '{sourceProp}' 不存在或为 null，跳过");
                continue;
            }

            JsonNode? mappedValue = rule.TargetType switch
            {
                TargetType.String => JsonValue.Create(sourceValue.ToString()),
                TargetType.Array => (sourceValue as JsonArray)?.DeepClone(),
                TargetType.Integer => int.TryParse(sourceValue.ToString(), out int n) ? JsonValue.Create(n) : null,
                TargetType.Boolean => JsonValue.Create(ParseBoolean(sourceValue.ToString())),
                _ => sourceValue.DeepClone()
            };

            if (mappedValue == null)
            {
                Console.WriteLine("  ❌ 映射失败，跳过");
                continue;
            }

            // ✅ 确保该位置是一个 JsonObject
            if (targetArray[i] is not JsonObject obj)
            {
                obj = new JsonObject();
                targetArray[i] = obj;
            }

            // ✅ 设置字段（合并，不是替换）
            obj[propName] = mappedValue;
            Console.WriteLine($"  ✅ 合并字段: [{i}].{propName} = {mappedValue.ToJsonString()}");
        }

        // ✅ 写回目标（但不要覆盖整个数组，因为可能已有其他字段）
        // 我们已经直接修改了 targetArray，所以只需确保它在 target 中
        if (!target.TryGetPropertyValue(arrayName, out _))
        {
            SetValueByPath(target, arrayName, targetArray); // 只有首次创建时才需要 SetValueByPath
        }

        Console.WriteLine($"\n🎯 数组 '{arrayName}' 合并完成，共 {targetArray.Count} 个元素");
        Console.WriteLine("========== ✅ 数组映射处理完成 ==========\n");
    }

    private static void HandleArrayExtraction(JsonObject target, JsonObject source, MappingRule rule)
    {
        Console.WriteLine($"[HandleArrayExtraction] Start: {rule.TargetPath} <= {rule.SourcePath}");

        // 提取源路径：app.team[*].skills
        var regex = new Regex(@"^(.+)\[\*\](?:\.(.+))?$");
        var match = regex.Match(rule.SourcePath);
        if (!match.Success)
        {
            Console.WriteLine("  → 无法解析源路径");
            return;
        }

        var arrayPath = match.Groups[1].Value;        // "app.team"
        var propInItem = match.Groups[2].Success ? match.Groups[2].Value : null; // "skills"

        // 获取数组
        var sourceArrayNode = source.GetValueOrNull(arrayPath);
        if (sourceArrayNode is not JsonArray sourceArray)
        {
            Console.WriteLine($"  → 未找到数组，位置在: {arrayPath}, 中的: {sourceArrayNode?.GetType().Name}");
            return;
        }

        Console.WriteLine($"  → 找到数据 {sourceArray.Count} 个");

        var targetArray = new JsonArray();

        for (int i = 0; i < sourceArray.Count; i++)
        {
            var item = sourceArray[i];
            if (item == null)
            {
                Console.WriteLine($"  → Item[{i}] is null");
                continue;
            }

            JsonNode? value;
            if (propInItem != null)
            {
                value = item.GetValueOrNull(propInItem);
            }
            else
            {
                value = item;
            }

            if (value != null)
            {
                targetArray.Add(value.DeepClone());
            }
            else
            {
                Console.WriteLine($"  → item[{i}] 是null");
            }
        }

        SetValueByPath(target, rule.TargetPath, targetArray);
    }

    private static void HandleSingleValueMapping(JsonObject target, JsonObject source, MappingRule rule)
    {
        Console.WriteLine($"\n========== 🔧 开始处理单值/对象映射 ==========");
        Console.WriteLine($"📌 规则：目标路径 = '{rule.TargetPath}' ← 源路径 = '{rule.SourcePath}'");

        if (rule.TargetType == TargetType.Const)
        {
            SetValueByPath(target, rule.TargetPath, rule.SourcePath);
            return;
        }

        // 获取源值（支持任意类型：string, int, object, array, bool）
        var sourceValue = source.GetValueOrNull(rule.SourcePath);
        if (sourceValue == null)
        {
            Console.WriteLine($"❌ 源路径 '{rule.SourcePath}' 不存在或值为 null，跳过");
            return;
        }

        JsonNode? mappedValue = null;

        try
        {
            mappedValue = rule.TargetType switch
            {
                TargetType.String => JsonValue.Create(sourceValue.ToString()),

                TargetType.Integer =>
                    int.TryParse(sourceValue.ToString(), out int n) ? JsonValue.Create(n) : null,

                TargetType.Boolean =>
                    JsonValue.Create(ParseBoolean(sourceValue.ToString())),

                TargetType.Array =>
                    (sourceValue as JsonArray)?.DeepClone(), // 克隆数组

                TargetType.Object =>
                    sourceValue.DeepClone(), // ✅ 克隆整个对象（或数组、任意结构）

                _ =>
                    sourceValue.DeepClone() // 默认深拷贝
            };
        }
        catch (Exception ex)
        {
            Console.WriteLine($"❌ 类型转换失败：{ex.Message}");
        }

        if (mappedValue == null)
        {
            Console.WriteLine($"❌ 映射结果为 null，跳过");
            return;
        }

        // 写入目标路径
        SetValueByPath(target, rule.TargetPath, mappedValue);

        Console.WriteLine($"✅ 成功映射: '{rule.SourcePath}' → '{rule.TargetPath}'");
        Console.WriteLine($"📄 值 = {mappedValue.ToJsonString()}");
        Console.WriteLine("========== ✅ 单值/对象映射完成 ==========\n");
    }

    private static bool ParseBoolean(string? value)
    {
        return value?.ToLowerInvariant() switch
        {
            "true" => true,
            "yes" => true,
            "1" => true,
            "on" => true,
            _ => false
        };
    }

    private static void SetValueByPath(JsonObject obj, string path, JsonNode value)
    {
        Console.WriteLine($"\n🔧 SetValueByPath: 尝试设置路径 '{path}'，值 = {value?.ToJsonString() ?? "null"}");

        if (obj == null)
        {
            Console.WriteLine("❌ 错误：目标对象为 null");
            return;
        }

        if (value == null)
        {
            Console.WriteLine("❌ 警告：要设置的值为 null，跳过");
            return;
        }

        var parts = path.Split('.');
        if (parts.Length == 0)
        {
            Console.WriteLine("❌ 路径为空，无法设置");
            return;
        }

        JsonObject current = obj;

        // 遍历路径的前 N-1 段，创建中间对象
        for (int i = 0; i < parts.Length - 1; i++)
        {
            var part = parts[i];
            Console.WriteLine($"  📂 处理中间路径: '{part}'");

            if (!current.TryGetPropertyValue(part, out JsonNode? next) || next is not JsonObject inner)
            {
                inner = new JsonObject();
                current[part] = inner;
                Console.WriteLine($"    ✅ 创建新对象: current[\"{part}\"] = {{}}");
            }
            else
            {
                Console.WriteLine($"    🔗 复用现有对象: current[\"{part}\"]");
            }

            current = inner;
        }

        // 设置最后一段（字段名）
        var finalKey = parts[^1];
        Console.WriteLine($"  💾 设置最终字段: current[\"{finalKey}\"] = {value.ToJsonString()}");

        try
        {
            // ✅ 使用 DeepClone 避免 "already has a parent" 错误
            current[finalKey] = value.DeepClone();
            Console.WriteLine($"  ✅ 成功设置: obj.{path} = {value.ToJsonString()}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"  ❌ 设置失败: {ex.Message}");
        }
    }
}